﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;
using Visifire.Charts;
using System.Windows.Threading;
using SalePoints.WcfServices;
using SystemX.Infrastructure;
using SalePoints.Models;

namespace SalePoints.Utility
{
	public static class ChartHelper
	{
		[Obsolete("Not in use.Can be removed after 2009")]
		public static void InitCharts(this List<Chart> charts,DataLegendGroup group,Action<Chart> titleClick, double trendlineWidth,int renderType,IntervalTypes intervalType,string XValueFormatStr) {
			var upperbound = 24;
			switch (group)
			{
				case DataLegendGroup.Hourly:
					upperbound = 24;
					break;
				case DataLegendGroup.Daily:
					upperbound = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
					break;
				case DataLegendGroup.Monthly:
					upperbound = 12;
					break;
			}
			var fakeData = new List<SalePoints.WcfServices.SalePointInfo>();
			var key = default(SalePoints.WcfServices.SalePointKey);
			foreach (var c in ChannelList)
			{
				foreach (var l in GetLegendList(group))
				{
					key = new SalePoints.WcfServices.SalePointKey
					{
						Channel = c,
						Legend = l,
						TimeFlag = DateTime.Now
					};
					for (int i = 0; i < upperbound; i++)
					{
						fakeData.Add(new SalePointInfo
						{
							Amount = 0,
							Flag = c.ToString(),
							Key = key,
							Point = i
						});
					}
				}//endof foreach
			}//endof foreach

			charts.ForEach(c => {
				c.DrawSalePoints(c.FilterData(fakeData), c.Tag.ToString(), titleClick, trendlineWidth, renderType, intervalType, XValueFormatStr, false,1);
			});
		}

		public static Chart DrawSalePoints(this Chart chart, List<SalePoints.WcfServices.SalePointInfo> data, string titleTxt, Action<Chart> titleClick, double dataPointWidth,int renderType,IntervalTypes intervalType,string XValueFormatStr,bool showTrendline,int yValueOption)
		{
			//title
			if (chart.Titles.Count == 0)
			{
				var title = new Title { Text = titleTxt, FontWeight = FontWeights.Bold, Cursor = Cursors.Hand};
				if (titleClick != null)
				{
					title.MouseLeftButtonDown += (sd, e) =>
					{
						titleClick(chart);
					};
				};
				chart.Titles.Add(title);
			};

			//axisx and axisY
			registerAxisXY(ref chart,data, intervalType, XValueFormatStr,yValueOption);
			//data manipulating
			RefreshSalePoints(chart,chart.FilterData(data), dataPointWidth,renderType,yValueOption);


			//trendline
			if (showTrendline)
			{
				registerTrendline(chart, dataPointWidth * 3);
			}
			if (AppSettingsHelper.GetAsBool("SalePoints.HChart.View3D")) {
				chart.View3D = true;
			}
			return chart;
		}
		public static void RefreshSalePoints(this Chart chart, IList<SalePoints.WcfServices.SalePointInfo> data, double trendlineWidth, int renderType,int yValueOption)
		{
			var renderAs = GetRenderType(renderType);
			chart.Series.Clear();
			var data1 = (from item in data
						 group item by item.Key into g
						 select new { Key = g.Key, Items = g }).ToList();

			var legend = default(DataSeries);
			var dp = default(DataPoint);
			for (int i = 0; i < data1.Count; i++)
			{
				legend = new DataSeries() { XValueType = ChartValueTypes.Time, Name = getLegendDesc(data1[i].Key.Legend), RenderAs = renderAs };
				setLegenColor(ref legend,data1[i].Key.Legend);
				var tempXValue=default(DateTime);
				foreach (var x in data1[i].Items)
				{
					tempXValue=x.Key.TimeFlag.Date.AddHours(x.Point);
					dp = new DataPoint() { YValue = (double)x.Amount, XValue =tempXValue , Width = trendlineWidth};
					if (yValueOption == SalePointOptions.AMOUNT)
					{
						dp.YValue = (double)x.Amount;
					}
					else if (yValueOption == SalePointOptions.NUM)
					{
						dp.YValue = (double)x.Num;
					}
					dp.ToolTipText = string.Format("{0}时至{1}时,#YValue",tempXValue.AddHours(-1).ToString("HH"),tempXValue.ToString("HH"));
					legend.DataPoints.Add(dp);
				}
				chart.Series.Add(legend);
			}
		}


		public static List<SalePointInfo> FilterData(this Chart c,List<SalePointInfo> rawData)
		{
			return rawData.Where(y => y.Key.Channel.ToString() == c.Tag.ToString()).OrderBy(x => x.Point).ToList();
		}
		//Helper methods
		private static void registerAxisXY(ref Chart chart,List<SalePoints.WcfServices.SalePointInfo> data,IntervalTypes intervalTypeX,string valFormatStrX,int yValueOption) {
			var axesX = new Axis { IntervalType = intervalTypeX, ValueFormatString = valFormatStrX/*"HH"*/, ScrollBarScale = 1 };
			//default max y value
			var yValueFrom0 = AppSettingsHelper.GetAsBool("SalePoints.HChart.YValueStartFromZero");
			var maxYValue = AppSettingsHelper.GetAsDouble("SalePoints.HChart.MaxYValue");
			maxYValue = maxYValue == double.NaN ? 500000d : maxYValue;
			var axesY =default(Axis);
			//max y value
			if (yValueOption == SalePointOptions.AMOUNT)
			{
				var tempPoint = Convert.ToDouble(data.Max(x=>x.Amount));
				axesY = new Axis { StartFromZero = yValueFrom0, Prefix = "￥", AxisMaximum = tempPoint };
			}
			else if (yValueOption == SalePointOptions.NUM)
			{
				var tempPoint = Convert.ToDouble(data.Max(x => x.Num));
				axesY = new Axis { StartFromZero = yValueFrom0, Prefix = "", AxisMaximum = tempPoint };
			}
			else {
				axesY = new Axis { StartFromZero = yValueFrom0, Prefix = "￥", AxisMaximum = maxYValue };
			}

			chart.AxesX.Clear();
			chart.AxesX.Add(axesX);

			chart.AxesY.Clear();
			chart.AxesY.Add(axesY);
		}
		private static void registerTrendline(Chart chart, double width)
		{
			if (chart.TrendLines.Count > 0) return;
			// Create TrendLine
			TrendLine trendLine = new TrendLine();
			// Set TrendLine properties
			trendLine.LineThickness = width;//TODO:Get the column's actual width
			trendLine.LineColor = new SolidColorBrush(Colors.Magenta);
			trendLine.Opacity = 0.2;
			trendLine.Orientation = Orientation.Vertical;
			// Add TrendLine to TrendLines collection of Chart
			chart.TrendLines.Add(trendLine);

			//mouse mover effect
			chart.PlotArea.MouseMove += (sd, e) =>
			{
				var dp = Convert.ToDateTime(e.XValue);
				chart.TrendLines[0].Value = dp.Date.AddHours(dp.Hour);
			};
		}
		public static RenderAs GetRenderType(int renderType) {
			if (!Enum.IsDefined(typeof(RenderAs), renderType)) return RenderAs.Column;
			return (RenderAs)Enum.Parse(typeof(RenderAs), renderType.ToString(),true);
		}

		public static SaleChannel AllChannel {
			get
			{
				return SaleChannel.HealthDep|SaleChannel.MailOrder|SaleChannel.Store|SaleChannel.Website;
			}
		}
		public static List<SaleChannel> ChannelList
		{
			get
			{
				return new List<SaleChannel> { 
					SaleChannel.HealthDep,
					SaleChannel.MailOrder,
					SaleChannel.Store,
					SaleChannel.Website
				};
			}
		}
		public static List<DataLegend> GetLegendList(DataLegendGroup group)
		{
			var retVal = new List<DataLegend>();
			switch (group)
			{
				case DataLegendGroup.Hourly:
					retVal = new List<DataLegend> { 
					DataLegend.HourlyToday,
					DataLegend.HourlyYesterday,
					DataLegend.MonthlyLastYear
					};
					break;
				case DataLegendGroup.Daily:
					retVal = new List<DataLegend> { 
						DataLegend.DailyLastMonth,
						DataLegend.DailyThisMonth,
						DataLegend.DailyLastYearSameMonth
					};
					break;
				case DataLegendGroup.Monthly:
					retVal = new List<DataLegend> { 
						DataLegend.MonthlyThisYear,
						DataLegend.MonthlyLastYear,
						DataLegend.MonthlyPlan
					};
					break;
			}
			return retVal;
		}
		/// <summary>
		/// 设置维背景颜色
		/// </summary>
		/// <param name="legend"></param>
		/// <param name="dataLegend"></param>
		private static void setLegenColor(ref DataSeries legend, DataLegend dataLegend)
		{
			var color = getLegendColor(dataLegend);
			if (color != default(Color)) {
				legend.Color = new SolidColorBrush(color);
			}
		}
		/// <summary>
		/// 获取维背景颜色.
		/// </summary>
		/// <param name="legend"></param>
		/// <returns></returns>
		private static Color getLegendColor(DataLegend legend) {
			var color = default(Color);
			if (LegendGroup1.Contains(legend)) {
				color = Colors.Red;
			}
			else if (LegendGroup2.Contains(legend))
			{
				color = Colors.Green;
			}
			else if (LegendGroup3.Contains(legend))
			{
				color = Colors.Blue;
			}
			return color;
		}
		private static List<DataLegend> LegendGroup1 = new List<DataLegend> { DataLegend.HourlyToday, DataLegend.DailyThisMonth , DataLegend.MonthlyThisYear };
		private static List<DataLegend> LegendGroup2 = new List<DataLegend> { DataLegend.HourlyYesterday, DataLegend.DailyLastMonth, DataLegend.MonthlyLastYear };
		private static List<DataLegend> LegendGroup3 = new List<DataLegend> { DataLegend.HourlyLastWeekSameDay, DataLegend.DailyLastYearSameMonth ,DataLegend.MonthlyPlan };
		private static string getLegendDesc(DataLegend legend) {
			var retVal = legend.ToString();
			switch (legend) { 
				case DataLegend.HourlyToday:
					retVal = "今天";
					break;
				case DataLegend.HourlyYesterday:
					retVal = "昨天";
					break;
				case DataLegend.HourlyLastWeekSameDay:
					retVal = "上周同期";
					break;
			}
			return retVal;
		}
	}
}
